package com.example.mymusicdisplay.view;

import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.example.mymusicdisplay.MusicManager;
import com.example.mymusicdisplay.R;
import com.example.mymusicdisplay.customview.LrcView;
import com.example.mymusicdisplay.data.MusicData;
import com.example.mymusicdisplay.data.lrc.LrcEntity;
import com.example.mymusicdisplay.databinding.FragmentPlayingMusicBinding;
import com.example.mymusicdisplay.utils.LrcGetUtil;
import com.example.mymusicdisplay.utils.MediaPlayerUtil;
import com.example.mymusicdisplay.utils.MusicUtils;
import com.example.mymusicdisplay.utils.TimeFormatUtil;
import com.example.mymusicdisplay.viewmodel.MusicViewModel;
import com.google.gson.internal.LinkedTreeMap;

import java.util.List;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;
import jp.wasabeef.glide.transformations.BlurTransformation;

public class PlayingMusicFragment extends Fragment {

    private static final String TAG = "PlayingMusicFragment";
    private FragmentPlayingMusicBinding mPlayingMusicBinding;
    private NavController mController;
    private MusicViewModel mMusicViewModel;

    public PlayingMusicFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mPlayingMusicBinding = DataBindingUtil
            .inflate(LayoutInflater.from(requireContext()),
                R.layout.fragment_playing_music, container, false);
        mMusicViewModel = new ViewModelProvider(
            requireActivity(), new ViewModelProvider.NewInstanceFactory()).get(MusicViewModel.class);
        mPlayingMusicBinding.setViewModel(mMusicViewModel);
        mPlayingMusicBinding.setLifecycleOwner(getViewLifecycleOwner());
        ViewCompat.setOnApplyWindowInsetsListener(mPlayingMusicBinding.playingTop, new OnApplyWindowInsetsListener() {
            @Override
            public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) v.getLayoutParams();
                layoutParams.topMargin = insets.getSystemWindowInsetTop();
                return insets;
            }
        });
        return mPlayingMusicBinding.getRoot();
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initData();
        initLiveDataObserver();
        initClickListener();
    }

    private void initData() {
        mController = Navigation.findNavController(mPlayingMusicBinding.getRoot());
        initLrcData();
        if (MediaPlayerUtil.getInstance().isPlaying()) {
            mPlayingMusicBinding.playingMusicView.startAnimal();
        } else {
            Log.d(TAG, "initData: nothing");
        }
    }

    private void initClickListener() {
        mPlayingMusicBinding.playingClose.setOnClickListener(view -> {
            mController.navigateUp();
        });
        mPlayingMusicBinding.playingBefore.setOnClickListener(view -> {
            MusicManager.getInstance().beforeMusic();
        });
        mPlayingMusicBinding.playingOrPause.setOnClickListener(view -> {
            if (MediaPlayerUtil.getInstance().isPlaying()) {
                MusicManager.getInstance().pauseMusic();
                mPlayingMusicBinding.playingMusicView.stopAnimal();
                mPlayingMusicBinding.lrcView.pause();
            } else {
                MusicManager.getInstance().playMusic();
                mPlayingMusicBinding.playingMusicView.startAnimal();
                mPlayingMusicBinding.lrcView.resume();
            }
        });
        mPlayingMusicBinding.playingNext.setOnClickListener(view -> {
            MusicManager.getInstance().nextMusic();
        });

        mPlayingMusicBinding.playingMusicView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mPlayingMusicBinding.lrcView.setVisibility(View.VISIBLE);
                mPlayingMusicBinding.playingMusicView.setVisibility(View.GONE);
            }
        });

        mPlayingMusicBinding.lrcView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mPlayingMusicBinding.lrcView.setVisibility(View.GONE);
                mPlayingMusicBinding.playingMusicView.setVisibility(View.VISIBLE);
            }
        });

        mPlayingMusicBinding.lrcView.setOnPlayIndicatorLineListener(new LrcView.OnPlayIndicatorLineListener() {
            @Override
            public void onPlay(long time, String content) {
                MediaPlayerUtil.getInstance().seekTo((int) time);
            }
        });
    }


    private void initLrcData() {
        LrcGetUtil.getLrc(mMusicViewModel.getCurrentMusic().getValue().getSingName())
            .observeOn(Schedulers.io())
            .subscribeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Object>() {
                @Override
                public void accept(Object o) throws Throwable {
                    LinkedTreeMap treeMap = (LinkedTreeMap) o;
                    LinkedTreeMap lrc = (LinkedTreeMap) treeMap.get("lrc");
                    Object lyric = lrc.get("lyric");
                    List<LrcEntity> lrcEntities = LrcEntity.parseLrc(lyric.toString());
                    mPlayingMusicBinding.lrcView.setLrcData(lrcEntities);
                }
            });
    }

    private void initLiveDataObserver() {
        mMusicViewModel.getPlayStatus().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
            @Override
            public void onChanged(Boolean aBoolean) {
                if (aBoolean) {
                    mPlayingMusicBinding.lrcView.resume();
                    mPlayingMusicBinding.playingMusicView.startAnimal();
                } else {
                    mPlayingMusicBinding.lrcView.pause();
                    mPlayingMusicBinding.playingMusicView.stopAnimal();
                }
            }
        });

        mMusicViewModel.getCurrentMusic().observe(getViewLifecycleOwner(), new Observer<MusicData>() {
            @Override
            public void onChanged(MusicData musicData) {
                Log.d(TAG, "onChanged: Glide");
                mPlayingMusicBinding.playingMusicDuration
                    .setText(TimeFormatUtil.formatTime((int) musicData.getDuration()));
                mPlayingMusicBinding.playingSeekbar.setMax((int) musicData.getDuration());
                mPlayingMusicBinding.playingOrPause.setImageResource(R.drawable.playing);
                mPlayingMusicBinding.playingMusicView.startAnimal();
                Bitmap musicCover = MusicUtils.getArtwork(requireContext(),
                    musicData.getSingId(),
                    musicData.getAlbumId(), true, false);
                mPlayingMusicBinding.playingMusicView.setMusicIcon(musicCover);
                musicData.setLocalCover(musicCover);
                Glide.with(requireContext())
                    .load(musicCover)
                    .apply(RequestOptions.bitmapTransform(new BlurTransformation(25, 35)))
                    .into(new CustomTarget<Drawable>() {
                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        }

                        @Override
                        public void onResourceReady(@NonNull Drawable resource, Transition<? super Drawable> transition) {
                            Drawable current = resource.getCurrent();
                            mPlayingMusicBinding.playingBackground.setBackground(current);
                        }
                    });
                initLrcData();
            }
        });

        mMusicViewModel.getProgress().observe(getViewLifecycleOwner(), new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                mPlayingMusicBinding.playingMusicCurrentTime
                    .setText(TimeFormatUtil.formatTime(integer));
                mPlayingMusicBinding.playingSeekbar.setProgress(integer);

                mPlayingMusicBinding.lrcView.updateTime(integer);
            }
        });

        mPlayingMusicBinding.playingSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                seekBar.setProgress(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mPlayingMusicBinding.playingMusicCurrentTime
                    .setText(TimeFormatUtil.formatTime(seekBar.getProgress()));
                MediaPlayerUtil.getInstance().seekTo(seekBar.getProgress());
            }
        });
    }
}